package com.one.rope.mvp.basecore.util;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.one.rope.mvp.basecore.third.aliyun.AliyunSmsSendVO;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.*;
import java.util.Map.Entry;

/**
 * JSON转换工具类
 */
public class JsonUtils {

  private static Logger logger = LoggerFactory.getLogger(JsonUtils.class);

  /**
   * java Map转换为Google Json
   *
   * @return Gson JsonObject
   */
  public static JsonObject mapToGoogleJson(Map<String, String> map) {
    JsonObject jsonObject = new JsonObject();
    for (Entry<String, String> entry : map.entrySet()) {
      jsonObject.addProperty(entry.getKey(), entry.getValue());
    }
    return jsonObject;
  }

  public static <T> T mapToObject(Map<String, Object> map, Class<T> beanClass) throws Exception {
    if (map == null) {
      return null;
    }
    try {
      T obj = beanClass.newInstance();
      org.apache.commons.beanutils.BeanUtils.populate(obj, map);
      return obj;
    } catch (Exception e) {
      return null;
    }
  }


  public static <T> T mapToFastxmlObject(Map<String, Object> map, Class<T> beanClass) {
    if (map == null) {
      return null;
    }
    final ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
    mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
    mapper.configure(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, false);
    mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
    mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
    final T pojo = mapper.convertValue(map, beanClass);
    return pojo;
  }


  @SuppressWarnings("unchecked")
  public static <T> T mapStringToObject(Map<String, String> map, Class<T> beanClass) {
    if (map == null) {
      return null;
    }
    try {
      String jsonString = JsonUtils.mapToJsonString(map);
      return (T) JsonUtils.stringToObject(jsonString, beanClass);
    } catch (Exception e) {
      return null;
    }
  }


  /**
   * Map 转换为net.sf.json.JSONObject
   *
   * @return net.sf.json.JSONObject
   */
  public static JSONObject mapToSfJson(Map<String, String> map) {
    JSONObject jsonObject = JSONObject.fromObject(map);
    return jsonObject;
  }

  public static JSONObject mapOjectToSfJson(Map<String, Object> map) {
    JSONObject jsonObject = JSONObject.fromObject(map);
    return jsonObject;
  }

  public static String mapToJsonString(Map<String, String> map) {
    JSONObject jsonObject = mapToSfJson(map);
    return jsonObject.toString();
  }

  public static String mapOjectToJsonString(Map<String, Object> map) {
    JSONObject jsonObject = mapOjectToSfJson(map);
    return jsonObject.toString();
  }

  /**
   * Object转换为net.sf.json.JSONObject
   *
   * @return net.sf.json.JSONObject
   */
  public static JSONObject objectToSfJson(Object object) {
    JSONObject jsonObject = JSONObject.fromObject(object);
    return jsonObject;
  }

  /**
   * 对象转换为Map<String,String>
   *
   * @return Map<String, String>
   */
  public static Map<String, String> objectToMap(Object object) {
    return objectToMap(object, false);
  }

  /**
   * Object 转换为Java Map
   *
   * @return Map<String, String>
   */
  public static Map<String, String> objectToMap(Object object, boolean ignoreEmpty) {
    JSONObject jsonObject = objectToSfJson(object);
    return jsonToMap(jsonObject, ignoreEmpty);
  }

  public static Map<String, Object> objectToMapObject(Object object) {
    JSONObject jsonObject = objectToSfJson(object);
    return jsonToMapObject(jsonObject);
  }

  @SuppressWarnings("unchecked")
  public static Map<String, Object> stringToFastJsonMapObject(String json) {
    return JSON.parseObject(json, Map.class);
  }

  public static Map<String, Object> objectToFastJsonMapObject(Object object) {
    String json = objectToJsonString(object);
    return stringToFastJsonMapObject(json);
  }

  /**
   * 类型转换
   *
   * @param object 对象
   * @param cls 类别
   * @return T
   */
  public static <T> T objectFastJsonToFastXmlObject(T object, Class<T> cls) {
    String json = objectToJsonString(object);
    return stringToFasterxmlObject(json, cls);
  }

  public static Map<String, Object> objectToFastXmlMapObject(Object object) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    //mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    Map<String, Object> map = mapper.convertValue(object, new TypeReference<Map<String, Object>>() {
    });
    return map;
  }

  public static SortedMap<String, Object> objectToFastXmlSortedMapObject(Object object) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    SortedMap<String, Object> map = mapper
        .convertValue(object, new TypeReference<SortedMap<String, Object>>() {
        });
    return map;
  }

  public static Map<String, String> objectToFastXmlMapString(Object object) {
    Map<String, Object> mapObj = objectToFastXmlMapObject(object);
    Map<String, String> map = new HashMap<>(mapObj.size());
    for (Entry<String, Object> item : mapObj.entrySet()) {
      map.put(item.getKey(), String.valueOf(item.getValue()));
    }
    return map;
  }

  /**
   * 字符串的Xml Object
   */
  public static Map<String, Object> stringToFastXmlMapObject(String json) {
    Map<String, Object> map = new HashMap<String, Object>();
    try {
      ObjectMapper mapper = new ObjectMapper();
      mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
      map = mapper.readValue(json, new TypeReference<Map<String, String>>() {
      });
      return map;
    } catch (Exception e) {
      logger.error(e.getMessage());
    }
    return null;
  }


  /**
   * net.sf.json 转换为 Map,目前不支持局部类
   *
   * @return Map<String, String>
   */
  public static Map<String, String> jsonToMap(JSONObject jsonObject, boolean ignoreEmpty) {
    Map<String, String> data = new HashMap<String, String>(10);
    Iterator<?> it = jsonObject.keys();
    // 遍历jsonObject数据，添加到Map对象
    while (it.hasNext()) {
      String key = String.valueOf(it.next());
      Object object = jsonObject.get(key);
      if (object.equals(null)) {
        continue;
      }
      String value = String.valueOf(object);
      if (ignoreEmpty && value.length() == 0) {
        continue;
      }
      data.put(key, value);
    }
    return data;
  }

  public static Map<String, Object> jsonToMapObject(JSONObject jsonObject) {
    Map<String, Object> data = new HashMap<String, Object>(10);
    Iterator<?> it = jsonObject.keys();
    // 遍历jsonObject数据，添加到Map对象
    while (it.hasNext()) {
      String key = String.valueOf(it.next());
      Object object = jsonObject.get(key);
      if (object.equals(null)) {
        continue;
      }
      data.put(key, object);
    }
    return data;
  }

  /**
   * 字符串转换为List<E>
   *
   * @param json 字符串
   * @param clz class
   * @return List<E>
   */
  public static <E> List<E> stringToList(String json, Class<E> clz) {
    return JSON.parseArray(json, clz);
  }

  /**
   * 字符串转换为Java Object
   *
   * @return Object
   */
  public static Object stringToObject(String json, Class<?> clz) {
    return JSON.parseObject(json, clz);
  }

  /**
   * 字符串转换为Java Object
   *
   * @return Object
   */
  public static <T> T jsonToObject(String json, Class<T> clz) {
    return JSON.parseObject(json, clz);
  }

  @SuppressWarnings("unchecked")
  public static Map<String, String> stringToMap(String json) {
    if (StringUtils.isEmpty(json)) {
      return null;
    }
    return JSON.parseObject(json, Map.class);
  }

  /**
   * 对象转换为JSON字符串
   *
   * @return Json String
   */
  public static String objectToJsonString(Object object) {
    return JSON.toJSONString(object);
  }

  public static String objectToFasterxmlJsonString(Object object) {
    if (object == null) {
      return "";
    }
    try {
      ObjectMapper mapper = new ObjectMapper();
      mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

      SimpleModule simpleModule = new SimpleModule();
      mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
      simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
      simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);

      mapper.registerModule(simpleModule);

      //ObjectWriter writer   = mapper.writer().withoutAttribute("property1").withoutAttribute("property2");
      //String json =writer.writeValueAsString(writer);
      String json = mapper.writeValueAsString(object);

      return json;
    } catch (JsonProcessingException e) {
      return "";
    }
  }

  public static <T> T stringToFasterxmlObject(String jsonString, Class<T> cls) {
    return stringToFasterxmlObject(jsonString, cls, false);
  }

  public static <T> T stringToFasterxmlObject(String jsonString, Class<T> cls,
      boolean failOnUnKnowProperties) {
    try {
      if (jsonString == null) {
        return null;
      }
      ObjectMapper mapper = new ObjectMapper();
      mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnKnowProperties);
      mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
      mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
      mapper.configure(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, false);
      mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
      mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

      T obj = (T) mapper.readValue(jsonString, cls);
      return obj;
    } catch (Exception e) {
      logger.error("stringToFasterxmlObject:content:" + jsonString, e);
      return null;
    }
  }

  public static <T> T stringToFasterxmlList(String jsonStr, TypeReference<T> valueTypeRef) {
    return stringToFasterxmlList(jsonStr, valueTypeRef, false);
  }

  /**
   * json数组转List List<UserBean> jsonToUserBeans = readValue(listToJson, new
   * TypeReference<List<UserBean>>() {
   */
  public static <T> T stringToFasterxmlList(String jsonStr, TypeReference<T> valueTypeRef,
      boolean failOnUnKnowProperties) {
    ObjectMapper mapper = new ObjectMapper();
    try {
      mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnKnowProperties);
      mapper.configure(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, false);
      return mapper.readValue(jsonStr, valueTypeRef);
    } catch (Exception e) {
    }

//		JavaType listType = mapper
//			    .getTypeFactory().constructArrayType(elementType)
//			    constructCollectionType(List.class, null);
//			List<?> users = mapper.readValue("", listType);
//			System.out.println(mapper.writeValueAsString(users));

    return null;
  }

  public static <T> T stringToFasterxmlList(String jsonStr, Class<?> elementType) {
    return stringToFasterxmlList(jsonStr, ArrayList.class, elementType);
  }

  public static <T> T stringToFasterxmlList(String jsonStr, Class<?> collectionClass,
      Class<?> elementType) {
    return stringToFasterxmlList(jsonStr, collectionClass, elementType, false);
  }

  /**
   * json字符串返回集合
   */
  public static <T> T stringToFasterxmlList(String jsonStr, Class<?> collectionClass,
      Class<?> elementType,
      boolean failOnUnKnowProperties) {
    ObjectMapper mapper = new ObjectMapper();
    try {
      mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnKnowProperties);
      mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
      mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
      //   mapper.configure(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, false);
      mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
      mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
      JavaType listType = mapper.getTypeFactory()
          .constructCollectionLikeType(collectionClass, elementType);
      return mapper.readValue(jsonStr, listType);
    } catch (Exception e) {
    }
    return null;
  }

  /**
   * 字符串转换为json
   *
   * @return JSONObject
   */
  public static com.alibaba.fastjson.JSONObject stringToJsonObject(String json) {
    return JSON.parseObject(json);
  }

  /**
   * Json String to Map
   *
   * @param json string
   * @return Map
   */
  @SuppressWarnings("serial")
  public static <T> Map<String, T> stringToMapGson(String json) {
    return new Gson().fromJson(json, new TypeToken<HashMap<String, T>>() {
    }.getType());
  }

  /**
   * 复杂类型：Json转化为bean<br> 用法示例：<br> Map<String, Class> classMap = new HashMap<String, Class>();
   * classMap.put("list", ChildBean.class); //指定复杂类型属性的映射关系，可以使多个放到map中<br> Person
   * person=(Person)JsonUtil.jsonString2Object(str2, Person.class, classMap);<br>
   */
  public static Object jsonString2Object(String jsonString, Class<?> pojoCalss,
      Map<String, Class<?>> classMap) {
    JSONObject jobj = JSONObject.fromObject(jsonString);

    return JSONObject.toBean(jobj, pojoCalss, classMap);
  }

  /**
   * 获取字段的名称
   */
  public static String getFieldName(Field field) {
    JsonProperty property = field.getAnnotation(JsonProperty.class);
    if (property != null && !com.one.rope.mvp.basecore.util.StringUtils
        .isNullOrEmpty(property.value())) {
      return property.value();
    }
    return field.getName();
  }

  public static JSONObject spliceJsonObject(JSONObject obj1, JSONObject obj2) {
    JSONObject jsonObject = new JSONObject();
    if (obj1.isEmpty() && obj2.isEmpty()) {
      return new JSONObject();
    }
    jsonObject = obj1;
    Iterator<String> iterator = obj2.keys();
    while (iterator.hasNext()) {
      String key = iterator.next();
      String value = obj2.getString(key);
      jsonObject.put(key, value);
    }
    return jsonObject;
  }

  public static void main(String[] args) {
//    JSONObject obj1 = new JSONObject();
//    obj1.put("name", "xiaoming");
//    JSONObject obj2 = new JSONObject();
//    obj1.put("age", "16");
//    JSONObject jsonObject = spliceJsonObject(obj1, obj2);
//    System.out.println(jsonObject.toString());
//    System.out.println(jsonObject.get("name"));
//    System.out.println(jsonObject.get("age"));
    String data = "{\"Message\":\"OK\",\"RequestId\":\"BFEA77D9-45B5-4A12-87FD-A33292063670\",\"BizId\":\"834705684210146249^0\",\"Code\":\"OK\"}";
    AliyunSmsSendVO smsSendVO = (AliyunSmsSendVO)JsonUtils.stringToObject(data, AliyunSmsSendVO.class);
    System.out.println(smsSendVO.getCode());
  }
}
